Los datos utilizados para esta práctica se pueden descargar del siguiente link. https://archive.ics.uci.edu/ml/datasets/bank+marketing
A continuación se cargan las librerías necesarias para el primer análisis
import os, sys
import numpy as np
import pandas as pd
import pandas_profiling ####Verificar que esté instalada. Si no está instalada, se puede utilziar el comando conda install -c conda-forge pandas-profiling --y
from IPython.display import Image
from matplotlib import pyplot as plt
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn import metrics
from sklearn.metrics import f1_score, roc_auc_score
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV #####Revisar esta librería.
from sklearn.neural_network import MLPClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
from sklearn import tree
from sklearn.metrics import confusion_matrix
from sklearn.metrics import recall_score
from sklearn.metrics import precision_score
from sklearn.metrics import classification_report
from sklearn.ensemble import GradientBoostingClassifier
#from sklearn.externals.six import StringIO
from IPython.display import Image
from sklearn.tree import export_graphviz
#import pydotplus
#from sklearn.externals import joblib
%cd C:\Users\USUARIO\Documents\monitoria_cda_2020_02\Clases_Python\Clase8_Python\bank-additional
##Importante, el archivo no está seoarada por comas, si no por punto y coma
data=pd.read_csv('bank-additional-full.csv', sep=";")
#######Esto es una prueba para leer los datos del parcial
#%cd C:\Users\USUARIO\Documents\monitoria_marketing\Parcial_marketing
##Codigo para leer data del parcial
#data_parcial = pd.read_excel('data_parcial.xlsx')
data.head()
A continnuación, se detalla las primeras filas del dataframe, con el fin de verificar que el archivo esté correctamente cargado
data.head()
A continuación, se obtiene el tipo de cada una de las variables.
data.dtypes
data.shape
Image(url= "https://www.ibmbigdatahub.com/sites/default/files/figure01_revised.jpg")
Metodologìa ASUM.
ver referencia https://www.ibmbigdatahub.com/blog/why-we-need-methodology-data-science
Los datos están relacionados con campañas de marketing de una institución bancaria portuguesa. Las campañas de marketing se basaron en llamadas telefónicas. A menudo, se requería más de un contacto con el mismo cliente para que el cliente se suscriba a un depósito a plazo. Por otra parte, la data que se cargó es la denominada "bank-additional-full", la cual contiene 41188 observacioes y 21 variables, y son observaciones ordenadas por fecha (de Mayo de 2008 a Noviembre de 2010), estos datos son los utilizados en [Moro et al., 2014]
Cada observación corresponde a un contacto con el cliente, esto es muy importante, dado que, según la descripción anterior, un cliente puede estar dos veces en la data, donde, en un contacto pudo no suscribirse y en segundo contacto si. En la siguiente ítem se analizarán las distintas variables del archivo.
Se puede observar distintos tipos de variables por ejemplo, age es numérico y representa a la edad del cliente, job o tipo de trabajo es categórco, estado civil categórico, nivel educativo categórico, por otra parte, la variable default indica si el cliente tiene créditos en mora o no y es categórica, housing indica si el cliente tiene o no vivienda y es categórica, loan indica si tiene o no préstamo y es categórica, contact indica la forma en la cual se contactó el cliente (de forma telefónica, por celular, etc), month indica el mes de contacto, day_of_week indica el día de la semana, duration indica la duración de la llamada, campaign indica la cantidad de días que pasaron después de que el cliente fue contactado por última vez desde una campaña anterior, pdays indica el número de días que han pasado desde el último contacto, esta variable es numérica, previous cantidad de contactos realizados antes de esta campaña y para este cliente, poutcome indica si la campaña anterior fue exitosa o no, la variable y indica si el cliente ha suscrito un depósito a plazo, esta variable es dicotómica.
A continuación, se realiza una revisión únicamente del primer registro.
data.loc[0, : ]
A continuación, se realiza un primer análisis de la data utilizando la función pandas profiling.
pandas_profiling.ProfileReport(data)
A continuación, se va estudiar si existe o no valores missing.
def missing_values_table(df):
mis_val = df.isnull().sum()
mis_val_percent = 100 * df.isnull().sum()/len(df)
mis_val_table = pd.concat([mis_val, mis_val_percent], axis=1)
mis_val_table_ren_columns = mis_val_table.rename(
columns = {0 : 'Missing Values', 1 : '% of Total Values'})
return mis_val_table_ren_columns
missing_values_table(data)
Como se puede observar, no existen valores missing en los datos, sin embargo, se realizará un análisis más profundo, variable por variable.
data["age"].describe()
data["age"].hist()
Como se puede observar, la variable edad presenta valores con un rango entre 17 y 98, por otra parte, la media es 40 años, por tanto, parece ser que no hay datos "raros"
## Frecuencia absoluta
#data['job'].describe()
pd.value_counts(data['job'])
## Frecuencia relativa
100 * data['job'].value_counts() / len(data['job'])
plot_frec_abs = data['job'].value_counts().plot(kind='bar', title='job')
Se puede observar que la variable trabajo presenta una categorìa denominada "unknown", que corresponde al 0,8% , por lo tanto, se procede a eliminar esta categoría.
data=data[data.job!="unknown"]
data2=data[data.job=="student"]
100 * data2['job'].value_counts() / len(data2['job'])
## Frecuencia absoluta
pd.value_counts(data['marital'])
## Frecuencia relativa
100 * data['marital'].value_counts() / len(data['marital'])
plot_frec_abs = data['marital'].value_counts().plot(kind='bar', title='marital')
Se procede a eliminar la categorìa unknown de la variable marital.
data=data[data.job!="unknown"]
## Frecuencia absoluta
pd.value_counts(data['education'])
## Frecuencia relativa
100 * data['education'].value_counts() / len(data['education'])
plot_frec_abs = data['education'].value_counts().plot(kind='bar', title='education')
Se procede a eliminar la categorìa unknown de la variable education.
data=data[data.education!="unknown"]
## Frecuencia absoluta
pd.value_counts(data['default'])
Esta variable no se debe utilizará para el análisis. ¿Por qué?
## Frecuencia absoluta
pd.value_counts(data['housing'])
## Frecuencia relativa
100 * data['housing'].value_counts() / len(data['housing'])
plot_frec_abs = data['housing'].value_counts().plot(kind='bar', title='housing')
Se procede a eliminar la categorìa unknown de la variable housing.
data=data[data.housing!="unknown"]
## Frecuencia absoluta
pd.value_counts(data['loan'])
## Frecuencia relativa
100 * data['loan'].value_counts() / len(data['loan'])
plot_frec_abs = data['loan'].value_counts().plot(kind='bar', title='loan')
Las siguientes variables fueron excludías del análisis month (mes) y duration (duración de la llamada), campaign ¿Por qué?
## Frecuencia absoluta
pd.value_counts(data['contact'])
## Frecuencia relativa
100 * data['contact'].value_counts() / len(data['contact'])
plot_frec_abs = data['contact'].value_counts().plot(kind='bar', title='contact')
data["pdays"].describe()
Como s puede observar, esta variable es numérica, sin embargo, 999 es un valor que indica que el cliente nunca ha sido contactado, por otra parte, por lo menos el 75 % de los datos indican que los clientes nunca se han tocado ppreviamente, por tanto, no se utilizará esta variable para un futuro análisis, sin embargo, se utilizará la variable previous, que indica la cantidad de veces que se han contactado con el cliente previamente.
data["previous"].describe()
data["previous"].hist()
## Frecuencia absoluta
pd.value_counts(data['poutcome'])
## Frecuencia relativa
100 * data['poutcome'].value_counts() / len(data['poutcome'])
plot_frec_abs = data['poutcome'].value_counts().plot(kind='bar', title='poutcome')
## Frecuencia absoluta
pd.value_counts(data['y'])
## Frecuencia relativa
100 * data['y'].value_counts() / len(data['y'])
plot_frec_abs = data['y'].value_counts().plot(kind='bar', title='y')
data_analisis=data.loc[:, ['age',
'job',
'marital',
'education',
'housing',
'loan',
'contact',
'previous',
'poutcome',
'y']]
###Función que permite discretizar una variable cuantitativa
def cate(x):
if x['age']<=32:
return '32'
elif x['age']>32 and x['age']<=38:
return '33-38'
elif x['age']>38 and x['age']<=47:
return '38-47'
elif x['age']>47 and x['age']<=60:
return '47-60'
else:
return '60'
##Crear una nueva variable denominada "grupo_edad"
data_analisis['grupo_edad']=data_analisis.apply(cate,axis=1)
##Frecuencia absoluta
pd.value_counts(data_analisis['grupo_edad'])
## Frecuencia relativa
100 * data_analisis['grupo_edad'].value_counts() / len(data_analisis['grupo_edad'])
A continuación, se construye una tabla de contigencia entre la variable grupo edad y la variable y
Tabla = pd.crosstab(index=data_analisis.grupo_edad,columns=data_analisis["y"],margins=True)
Tabla.index= ["32","33-38", "38-47", "47-60", "60", "Total y"] # Para las filas, pero el último elemento es el total de la "columna"
Tabla.columns= ["no", 'yes', "Total_edad"] # Para las columnas, pero el último elemento es el total de la "fila"
Tabla
####Frecuencia relativa filas
table2 = Tabla.div(Tabla.Total_edad, axis=0)
table2
colors_list = ['#5cb85c','#5bc0de','#d9534f']
# Change this line to plot percentages instead of absolute values
ax = (table2[["no", "yes"]]).plot(kind='bar',figsize=(15,4),width = 0.8,color = colors_list,edgecolor=None)
plt.legend(labels=Tabla.columns,fontsize= 14)
plt.title("Porcentaje de aceptación por edad",fontsize= 16)
plt.xticks(fontsize=14)
for spine in plt.gca().spines.values():
spine.set_visible(False)
plt.yticks([])
# Add this loop to add the annotations
for p in ax.patches:
width, height = p.get_width(), p.get_height()
x, y = p.get_xy()
ax.annotate('{:.0%}'.format(height), (x, y + height + 0.01))
Se pede pensar en realizar una campaña enfocada a las personas mayor a 60 años.
Tabla = pd.crosstab(index=data_analisis.job,columns=data_analisis["y"],margins=True)
Tabla.index= ['admin',
'blue-collar',
'entrepreneur',
'housemaid',
'management',
'retired',
'self-employed',
'services',
'student',
'technician',
'unemployed', "Total y"] # Para las filas, pero el último elemento es el total de la "columna"
Tabla.columns= ["no", 'yes', "Total_job"] # Para las columnas, pero el último elemento es el total de la "fila"
Tabla
####Frecuencia relativa filas
table2 = Tabla.div(Tabla.Total_job, axis=0)
table2
colors_list = ['#5cb85c','#5bc0de','#d9534f']
# Change this line to plot percentages instead of absolute values
ax = (table2[["no", "yes"]]).plot(kind='bar',figsize=(25,5),width = 0.8,color = colors_list,edgecolor=None)
plt.legend(labels=Tabla.columns,fontsize= 14)
plt.title("Porcentaje de aceptación por edad",fontsize= 16)
plt.xticks(fontsize=14)
for spine in plt.gca().spines.values():
spine.set_visible(False)
plt.yticks([])
# Add this loop to add the annotations
for p in ax.patches:
width, height = p.get_width(), p.get_height()
x, y = p.get_xy()
ax.annotate('{:.0%}'.format(height), (x, y + height + 0.01))
Se puede pensar en realziar campañas enfocadas hacia los estudiantes y los retirados.
Tabla = pd.crosstab(index=data_analisis.contact,columns=data_analisis["y"],margins=True)
Tabla.index= ["cellular","telephone", "Total y"] # Para las filas, pero el último elemento es el total de la "columna"
Tabla.columns= ["no", 'yes', "Total_contact"] # Para las columnas, pero el último elemento es el total de la "fila"
Tabla
####Frecuencia relativa filas
table2 = Tabla.div(Tabla.Total_contact, axis=0)
table2
colors_list = ['#5cb85c','#5bc0de','#d9534f']
# Change this line to plot percentages instead of absolute values
ax = (table2[["no", "yes"]]).plot(kind='bar',figsize=(15,4),width = 0.8,color = colors_list,edgecolor=None)
plt.legend(labels=Tabla.columns,fontsize= 14)
plt.title("Porcentaje de aceptación por edad",fontsize= 16)
plt.xticks(fontsize=14)
for spine in plt.gca().spines.values():
spine.set_visible(False)
plt.yticks([])
# Add this loop to add the annotations
for p in ax.patches:
width, height = p.get_width(), p.get_height()
x, y = p.get_xy()
ax.annotate('{:.0%}'.format(height), (x, y + height + 0.01))
Se puede pensar en realziar campañas enfocadas hacia los clientes que tienen celular. Por telefono nno responden mucho.
Tabla = pd.crosstab(index=data_analisis.loan,columns=data_analisis["y"],margins=True)
Tabla.index= ["no","yes", "Total y"] # Para las filas, pero el último elemento es el total de la "columna"
Tabla.columns= ["no", 'yes', "Total_loan"] # Para las columnas, pero el último elemento es el total de la "fila"
Tabla
####Frecuencia relativa filas
table2 = Tabla.div(Tabla.Total_loan, axis=0)
table2
colors_list = ['#5cb85c','#5bc0de','#d9534f']
# Change this line to plot percentages instead of absolute values
ax = (table2[["no", "yes"]]).plot(kind='bar',figsize=(15,4),width = 0.8,color = colors_list,edgecolor=None)
plt.legend(labels=Tabla.columns,fontsize= 14)
plt.title("Porcentaje de aceptación por edad",fontsize= 16)
plt.xticks(fontsize=14)
for spine in plt.gca().spines.values():
spine.set_visible(False)
plt.yticks([])
# Add this loop to add the annotations
for p in ax.patches:
width, height = p.get_width(), p.get_height()
x, y = p.get_xy()
ax.annotate('{:.0%}'.format(height), (x, y + height + 0.01))
Analizando el gráfico anterior, se puede observar que la variable loan no influye sobre el porcentaje de aceptación a la campaña.
##Eliminar la variable grupo_edad
del data_analisis['grupo_edad']
data_analisis.head()
A continuación, se redefine la variable y de la siguiente forma:
###Función que permite discretizar una variable cuantitativa
def cate(x):
if x['y']=="yes":
return 1
else:
return '0'
##Crear una nueva variable denominada "grupo_edad"
data_analisis['target']=data_analisis.apply(cate,axis=1)
pd.value_counts(data_analisis["target"])
del data_analisis["y"]
data_analisis.dtypes
data_analisis['target'] = data_analisis['target'].astype(int)
Convertir variables categóricas a dummies.
data_model = pd.get_dummies(data_analisis)
data_model.dtypes
Para cambiar el orden de las variables.
columnsTitles = ["age",
"previous",
"job_admin.",
"job_blue-collar",
"job_entrepreneur",
"job_housemaid",
"job_management",
"job_retired" ,
"job_self-employed",
"job_services",
"job_student",
"job_technician",
"job_unemployed",
"marital_divorced",
"marital_married",
"marital_single",
"marital_unknown",
"education_basic.4y",
"education_basic.6y",
"education_basic.9y",
"education_high.school",
"education_illiterate",
"education_professional.course",
"education_university.degree",
"housing_no",
"housing_yes",
"loan_no",
"loan_yes",
"contact_cellular",
"contact_telephone",
"poutcome_failure",
"poutcome_nonexistent",
"poutcome_success",
"target"]
data_model = data_model.reindex(columns=columnsTitles)
data_model.dtypes
A continuación, se realiza una partición sobre la data.
###Partición de la data sobre entrenamiento y validacion.
X, y = data_model.iloc[:,0:33],data_model.iloc[:,33:34]
##Selección data de entrenamiento y test
X_train, X_test_pre, y_train, y_test_pre = train_test_split(X, y, test_size=0.3, random_state=3)
##Selección data de test y developer para tunnear los hiperparámetros
X_dev, X_test, Y_dev, Y_test = train_test_split(X_test_pre, y_test_pre, test_size=0.5, random_state=3)
def eval_model(X_train, y_train, X_test, y_test):
"""
Función para obtener los hiperparámetros del modelo árboles de decisión
Parámetros: Recibe como parámetros los datos de entrenamiento y los datos de desarrollo.
únicamente encuentra la mejor combinaciones de los marámetros max depth, mas features,
max_depth, max_features.
"""
vector_n_estimators=[1] ## No es un parametro
lr_list = [1] # No se va considerar
vector_max_depth=[1, 2, 3, 4, 5, ] ##si es un parámetro
max_features=[9, 12, 14] ##si es un parametro
for r in lr_list:
for p in vector_max_depth:
for f in max_features:
for e in vector_n_estimators:
#alg = DecisionTreeClassifier(criterion = "entropy",
# random_state = 100,
# max_depth=30, min_samples_leaf=5)
#criterion{“gini”, “entropy”}, default=”gini”
alg = DecisionTreeClassifier(#n_estimators=e,
#learning_rate=r,
max_features=f,
max_depth=p,
random_state=0)
##Inicio del entrenamiento
alg.fit(X_train, y_train)
# Para comenzar con la prediccion sobre test
predictions = alg.predict(X_test)
pred_proba = alg.predict_proba(X_test)[:, 1]
# Para comenzar con la predicción sobre train
predictions_train = alg.predict(X_train)
pred_proba_train = alg.predict_proba(X_train)[:, 1]
dif_accuracy = abs(metrics.f1_score(y_train, predictions_train) - metrics.f1_score(y_test, predictions))
##Para imprimer las predicciones sobre cada combinación de hiperparámetros.
print("#####################################")
print("max_depth: ", p, "max_features: ", f)
print("#####################################")
print("f1_score sobre datos de train")
print(metrics.f1_score(y_train, predictions_train))
print('f1_score sobre datos de desarrollo')
print(metrics.f1_score(y_test, predictions))
print("Diferencia entre el f1_score obtenido en test y desarrollo")
print(dif_accuracy)
##Para aplicar la fución anterior.
eval_model(X_train, y_train, X_dev, Y_dev)
Los mejores hiperparámetros encontrados son cuando max_depth = 5 y max features = 14, entonces, se utiliza este modelo, dado que la métrica que consideramos para este ejercicio es el f1 score.
def tree_classifier(X_train, X_test, y_train, y_test):
"""
Función para estimar un modelo utilizando árboles de decisión
Esta funciòn recibe como parametros los datos de entrenamiento y de test
Finalmente, imprime el AUC, f1-score, precision, recall, accuracy
por cada clase, tanto para la data de entrenamiento, como la de test.
Finaalmente, esta función también imprime la importancia de las variables.
"""
alg = DecisionTreeClassifier(#n_estimators=e,
#learning_rate=r,
max_features=14,
max_depth=5,
random_state=0)
# Entrenamiento
print('Inicio entrenamiento')
alg.fit(X_train, y_train)
# Guardar el modelo en disco en el siguiente directorio
# save the model to disk
#%cd C:\Users\\USUARIO\\Documents\\Monitoria_cda_2019_2\\Clases_Python\\Clase8_Python
#filename = 'finalized_model.sav'
#joblib.dump(alg, filename)
# Para comenzar con la prediccion
print("Iniciar la predicciòn")
predictions = alg.predict(X_test)
pred_proba = alg.predict_proba(X_test)[:, 1]
predictions_train = alg.predict(X_train)
pred_proba_train = alg.predict_proba(X_train)[:, 1]
#Para imprimir las metricas al aplicar el modelo sobre los datos de train
# Para imprimir las métricas al aplicar el modelo sobre los datos de test
print("Metricas al aplicar el modelo sobre los datos de train ")
print("Accuracy sobtr train")
print(metrics.accuracy_score(y_train, predictions_train))
print("AUC sobre train")
print(metrics.roc_auc_score(y_train, pred_proba_train))
print("Matriz de confusion sobre train")
print(confusion_matrix(y_train, predictions_train))
print("Recall sobre train")
print(metrics.recall_score(y_train, predictions_train))
print("Precision sobre train")
print(metrics.precision_score(y_train, predictions_train))
print("f1-Score sobre train")
print( metrics.f1_score(y_train, predictions_train))
print("Reporte clasificación sobre train")
print(classification_report(y_train, predictions_train))
# Para imprimir las métricas al aplicar el modelo sobre los datos de test
print("Metricas al aplicar el modelo sobre los datos de test ")
print("Accuracy sobre test")
print(metrics.accuracy_score(y_test, predictions))
print("AUC sobre test")
print(metrics.roc_auc_score(y_test, pred_proba))
print("Matriz de confusion sobre test")
print(confusion_matrix(y_test, predictions))
print("Recall sobre test")
print(metrics.recall_score(y_test, predictions))
print("Precision sobre test")
print(metrics.precision_score(y_test, predictions))
print("f1-Score sobre test")
print( metrics.f1_score(y_test, predictions))
print("Reporte clasificación sobre test")
print(classification_report(y_test, predictions))
feat_imp = alg.feature_importances_
feat = X_train.columns.tolist()
# clf.best_estimator_.booster().get_fscore()
res_df = pd.DataFrame({'Features': feat, 'Importance': feat_imp}).sort_values(by='Importance', ascending=False)
res_df.plot('Features',
'Importance',
kind='bar',
title='Feature Importances',
color= "blue")
plt.ylabel('Feature Importance Score')
plt.show()
print(res_df)
print(res_df["Features"].tolist())
tree_classifier(X_train, X_test, y_train, Y_test)
def eval_model(X_train, y_train, X_test, y_test):
"""
Función para obtener los hiperparámetros del modelo random forest.
Parámetros: Recibe como parámetros los datos de entrenamiento y los datos de desarrollo.
únicamente encuentra la mejor combinaciones de los marámetros n_estimators, learning_rate,
max_depth, max_features.
"""
vector_n_estimators=[40, 60, 100] ## si va
lr_list = [1] ## No va
vector_max_depth=[3, 6, 9] ## si va
max_features=[9, 12, 14] ## si va
for r in lr_list:
for p in vector_max_depth:
for f in max_features:
for e in vector_n_estimators:
alg = RandomForestClassifier(n_estimators=e,
#learning_rate=r,
max_features=f,
max_depth=p,
random_state=0)
##Inicio del entrenamiento
alg.fit(X_train, y_train)
# Para comenzar con la prediccion sobre test
predictions = alg.predict(X_test)
pred_proba = alg.predict_proba(X_test)[:, 1]
# Para comenzar con la predicción sobre train
predictions_train = alg.predict(X_train)
pred_proba_train = alg.predict_proba(X_train)[:, 1]
dif_accuracy = abs(metrics.f1_score(y_train, predictions_train) - metrics.f1_score(y_test, predictions))
##Para imprimer las predicciones sobre cada combinación de hiperparámetros.
print("#####################################")
print("max_depth: ", p, "max_features: ", f, "n_estimators: ", e)
print("#####################################")
print("f1_score sobre datos de train")
print(metrics.f1_score(y_train, predictions_train))
print('f1_score sobre datos de desarrollo')
print(metrics.f1_score(y_test, predictions))
print("Diferencia entre el f1_score obtenido en test y desarrollo")
print(dif_accuracy)
##Para aplicar la fución anterior.
eval_model(X_train, y_train, X_dev, Y_dev)
Los mejores hiperparámetros para el random forest son: max_depth: 9 max_features: 12 n_estimators: 100
def tree_classifier(X_train, X_test, y_train, y_test):
"""
Función para estimar un modelo utilizando random forest
Esta funciòn recibe como parametros los datos de entrenamiento y de test
Finalmente, imprime el AUC, f1-score, precision, recall, accuracy
por cada clase, tanto para la data de entrenamiento, como la de test.
Finaalmente, esta función también imprime la importancia de las variables.
"""
alg = RandomForestClassifier(n_estimators=100,
#learning_rate=r,
max_features=12,
max_depth=9,
random_state=0)
# Entrenamiento
print('Inicio entrenamiento')
alg.fit(X_train, y_train)
# Guardar el modelo en disco en el siguiente directorio
# save the model to disk
#%cd C:\Users\\USUARIO\\Documents\\Monitoria_cda_2019_2\\Clases_Python\\Clase8_Python
#filename = 'finalized_model.sav'
#joblib.dump(alg, filename)
# Para comenzar con la prediccion
print("Iniciar la predicciòn")
predictions = alg.predict(X_test)
pred_proba = alg.predict_proba(X_test)[:, 1]
predictions_train = alg.predict(X_train)
pred_proba_train = alg.predict_proba(X_train)[:, 1]
#Para imprimir las metricas al aplicar el modelo sobre los datos de train
# Para imprimir las métricas al aplicar el modelo sobre los datos de test
print("Metricas al aplicar el modelo sobre los datos de train ")
print("Accuracy sobtr train")
print(metrics.accuracy_score(y_train, predictions_train))
print("AUC sobre train")
print(metrics.roc_auc_score(y_train, pred_proba_train))
print("Matriz de confusion sobre train")
print(confusion_matrix(y_train, predictions_train))
print("Recall sobre train")
print(metrics.recall_score(y_train, predictions_train))
print("Precision sobre train")
print(metrics.precision_score(y_train, predictions_train))
print("f1-Score sobre train")
print( metrics.f1_score(y_train, predictions_train))
print("Reporte clasificación sobre train")
print(classification_report(y_train, predictions_train))
# Para imprimir las métricas al aplicar el modelo sobre los datos de test
print("Metricas al aplicar el modelo sobre los datos de test ")
print("Accuracy sobre test")
print(metrics.accuracy_score(y_test, predictions))
print("AUC sobre test")
print(metrics.roc_auc_score(y_test, pred_proba))
print("Matriz de confusion sobre test")
print(confusion_matrix(y_test, predictions))
print("Recall sobre test")
print(metrics.recall_score(y_test, predictions))
print("Precision sobre test")
print(metrics.precision_score(y_test, predictions))
print("f1-Score sobre test")
print( metrics.f1_score(y_test, predictions))
print("Reporte clasificación sobre test")
print(classification_report(y_test, predictions))
feat_imp = alg.feature_importances_
feat = X_train.columns.tolist()
# clf.best_estimator_.booster().get_fscore()
res_df = pd.DataFrame({'Features': feat, 'Importance': feat_imp}).sort_values(by='Importance', ascending=False)
res_df.plot('Features',
'Importance',
kind='bar',
title='Feature Importances',
color= "blue")
plt.ylabel('Feature Importance Score')
plt.show()
print(res_df)
print(res_df["Features"].tolist())
tree_classifier(X_train, X_test, y_train, Y_test)
def eval_model(X_train, y_train, X_test, y_test):
"""
Función para obtener los hiperparámetros del modelo gradient boosting.
Parámetros: Recibe como parámetros los datos de entrenamiento y los datos de desarrollo.
únicamente encuentra la mejor combinaciones de los marámetros n_estimators, learning_rate,
max_depth, max_features.
"""
vector_n_estimators=[40, 80, 100]
lr_list = [0.3]
vector_max_depth=[3, 5]
max_features=[9, 12]
for r in lr_list:
for p in vector_max_depth:
for f in max_features:
for e in vector_n_estimators:
alg = GradientBoostingClassifier(n_estimators=e,
learning_rate=r,
max_features=f,
max_depth=p,
random_state=0)
##Inicio del entrenamiento
alg.fit(X_train, y_train)
# Para comenzar con la prediccion sobre test
predictions = alg.predict(X_test)
pred_proba = alg.predict_proba(X_test)[:, 1]
# Para comenzar con la predicción sobre train
predictions_train = alg.predict(X_train)
pred_proba_train = alg.predict_proba(X_train)[:, 1]
dif_accuracy = abs(metrics.f1_score(y_train, predictions_train) - metrics.f1_score(y_test, predictions))
##Para imprimer las predicciones sobre cada combinación de hiperparámetros.
print("#####################################")
print("learning_rate: ", r , "max_depth: ", p, "max_features: ", f, "n_estimators: ", e)
print("f1_score sobre datos de train")
print(metrics.f1_score(y_train, predictions_train))
print('f1_score sobre datos de desarrollo')
print(metrics.f1_score(y_test, predictions))
print("Diferencia entre el f1_score obtenido en test y desarrollo")
print(dif_accuracy)
##Para aplicar la fución anterior.
eval_model(X_train, y_train, X_dev, Y_dev)
Los mejores hiperparámetros son learning_rate: 0.3 max_depth: 5 max_features: 12 n_estimators: 40
def xgb_classifier(X_train, X_test, y_train, y_test):
"""
Función para estimar un modelo utilizando gradient boosting machine (esemble)
Esta funciòn recibe como parametros los datos de entrenamiento y de test
Finalmente, imprime el AUC, f1-score, precision, recall, accuracy
por cada clase, tanto para la data de entrenamiento, como la de test.
Finaalmente, esta función también imprime la importancia de las variables.
"""
alg = GradientBoostingClassifier(n_estimators=40,
learning_rate=0.3,
max_features=12,
max_depth=5, random_state=0)
# Entrenamiento
print('Inicio entrenamiento')
alg.fit(X_train, y_train)
# Guardar el modelo en disco en el siguiente directorio
# save the model to disk
#%cd C:\Users\\USUARIO\\Documents\\Monitoria_cda_2019_2\\Clases_Python\\Clase8_Python
#filename = 'finalized_model.sav'
#joblib.dump(alg, filename)
# Para comenzar con la prediccion
print("Iniciar la predicciòn")
predictions = alg.predict(X_test)
pred_proba = alg.predict_proba(X_test)[:, 1]
predictions_train = alg.predict(X_train)
pred_proba_train = alg.predict_proba(X_train)[:, 1]
#Para imprimir las metricas al aplicar el modelo sobre los datos de train
# Para imprimir las métricas al aplicar el modelo sobre los datos de test
print("Metricas al aplicar el modelo sobre los datos de train ")
print("Accuracy sobtr train")
print(metrics.accuracy_score(y_train, predictions_train))
print("AUC sobre train")
print(metrics.roc_auc_score(y_train, pred_proba_train))
print("Matriz de confusion sobre train")
print(confusion_matrix(y_train, predictions_train))
print("Recall sobre train")
print(metrics.recall_score(y_train, predictions_train))
print("Precision sobre train")
print(metrics.precision_score(y_train, predictions_train))
print("f1-Score sobre train")
print( metrics.f1_score(y_train, predictions_train))
print("Reporte clasificación sobre train")
print(classification_report(y_train, predictions_train))
# Para imprimir las métricas al aplicar el modelo sobre los datos de test
print("Metricas al aplicar el modelo sobre los datos de test ")
print("Accuracy sobre test")
print(metrics.accuracy_score(y_test, predictions))
print("AUC sobre test")
print(metrics.roc_auc_score(y_test, pred_proba))
print("Matriz de confusion sobre test")
print(confusion_matrix(y_test, predictions))
print("Recall sobre test")
print(metrics.recall_score(y_test, predictions))
print("Precision sobre test")
print(metrics.precision_score(y_test, predictions))
print("f1-Score sobre test")
print( metrics.f1_score(y_test, predictions))
print("Reporte clasificación sobre test")
print(classification_report(y_test, predictions))
feat_imp = alg.feature_importances_
feat = X_train.columns.tolist()
# clf.best_estimator_.booster().get_fscore()
res_df = pd.DataFrame({'Features': feat, 'Importance': feat_imp}).sort_values(by='Importance', ascending=False)
res_df.plot('Features',
'Importance',
kind='bar',
title='Feature Importances',
color= "blue")
plt.ylabel('Feature Importance Score')
plt.show()
print(res_df)
print(res_df["Features"].tolist())
xgb_classifier(X_train, X_test, y_train, Y_test)